/**
 * 	write on 2005-10-26 12:38:32.
 */
package org.nanhill.xmlro.gsp;

import static org.nanhill.xmlro.gsp.GspConstants.GSP_END;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;

import org.nanhill.xmlro.AbstractXmlroTransport;
import org.nanhill.xmlro.SerializerFactory;
import org.nanhill.xmlro.XmlroException;
import org.nanhill.xmlro.XmlroInput;
import org.nanhill.xmlro.gsp.model.GspSerializerFactory;
import org.nanhill.xmlro.gsp.packet.GspPacket;

/**
 * @author alin
 * 
 */
public class GspTransport extends AbstractXmlroTransport {
	private static final GspVersion DEFAULT_VERSION = GspVersion.V2;

	private static final SerializerFactory DEFAULT_SERIALIZER_FACTORY = new GspSerializerFactory();

	private GspVersion verion = DEFAULT_VERSION;

	private SerializerFactory serializerFactory = DEFAULT_SERIALIZER_FACTORY;

	public void setSerializerFactory(SerializerFactory serializerFactory) {
		this.serializerFactory = serializerFactory;
	}

	public void setVersion(GspVersion v) {
		this.verion = v;
	}

	public GspPacket receivePacket(InputStream inputStream) throws GspException, IOException {
		try {
			String xml = this.getXml(inputStream);
			return receivePacket(xml);
		} catch (XmlroException e) {
			throw new GspException(e);
		}
	}

	public GspPacket receivePacket(String xml) throws GspException {
		GspInput input = (GspInput) getInput();
		input.setReader(new StringReader(xml));
		GspPacket packet = input.echoGsp();
		return packet;
	}

	public <E> GspPacket<E> receivePacket(E wrap, InputStream inputStream)
			throws GspException, IOException {
		try {
			String xml = this.getXml(inputStream);
			return receivePacket(wrap, xml);
		} catch (XmlroException e) {
			throw new GspException(e);
		}
	}

	public <E> GspPacket<E> receivePacket(E wrap, String xml)
			throws GspException {
		GspInput<E> input = (GspInput<E>) getWrappedInput(wrap);
		input.setReader(new StringReader(xml));
		GspPacket<E> packet = input.echoGsp();
		return packet;
	}

	public <E> GspPacket<E> receivePacket(Class<E> wrapClz,
			InputStream inputStream) throws GspException, IOException {
		try {
			return receivePacket(wrapClz, this.getXml(inputStream));
		} catch (XmlroException e) {
			throw new GspException(e);
		}
	}

	@SuppressWarnings("unchecked")
	public <E> GspPacket<E> receivePacket(Class<E> wrapClz, String xml)
			throws GspException {
		GspInput<E> input = (GspInput<E>) getWrappedInput(wrapClz);
		input.setReader(new StringReader(xml));
		GspPacket<E> packet = input.echoGsp();
		return packet;
	}

	@Override
	protected XmlroInput getInput() {
		XmlroInput input;
		switch (this.verion) {
		case V1:
			input = new GspInput();
			break;
		default:
			input = new GspInputV2();
		}
		return input;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected <E> XmlroInput<E> getWrappedInput(E wrap) {
		XmlroInput<E> input = this.getInput();
		if (null != wrap) {
			input.setWrap(wrap);
		}
		return input;
	}

	@SuppressWarnings("unchecked")
	@Override
	protected <E> XmlroInput<E> getWrappedInput(Class<E> wrapClz) {
		XmlroInput<E> input = this.getInput();
		if (null != wrapClz) {
			input.wrapClz(wrapClz);
		}
		return input;
	}

	@Override
	protected GspOutput getOutput() {
		GspOutput output = null;
		switch (this.verion) {
		case V1:
			output = new GspOutput();
			break;
		case V2:
			output = new GspOutputV2();
			break;
		}
		output.setSerializerFactory(this.serializerFactory);
		return output;
	}

	@Override
	protected String getEndFlag() {
		return GSP_END;
	}

	public void send(Object in, OutputStream outputStream) throws GspException,
			IOException {
		String out = this.send(in);
		outputStream.write(out.getBytes(characterSet));
		outputStream.flush();
	}

	public String send(Object in) throws GspException {
		GspOutput output = this.getOutput();
		output.setParsed(in);
		output.construct();
		String product = output.getProduct().toString();
		return product;
	}

	// public String parsePacket(GspPacket packet) throws XmlroException {
	// GspOutput output = new GspOutput(packet);
	// output.construct();
	// String product = output.getProduct().toString();
	// return product;
	// }

	// public GspPacket submit(GspPacket packet, InputStream inputStream,
	// OutputStream outputStream) throws IOException, XmlroException {
	// // --- do send data ---
	// outputStream.write(this.parsePacket(packet).getBytes());
	// // --- do recieve data--
	// BufferedReader in = new BufferedReader(new InputStreamReader(
	// inputStream));
	// StringBuilder sb = new StringBuilder();
	// String str;
	// while ((str = in.readLine()) != null) {
	// sb.append(str);
	// if (str.endsWith(GSP_END)) {
	// break;
	// }
	// }
	// return this.parseXml(sb.toString());
	// }

}
